package com.ji.collection;

import com.google.common.collect.*;

import java.util.Collection;
import java.util.Map;
import java.util.Set;

/**
 * Multiset
 * Multimap
 * Bimap
 * table
 * RangeSet
 * RangeMap
 */
public class CollectionMy {
    public static void main(String[] args) {
        //####可计数的set#########
        //  Map	对应的Multiset	是否支持null元素
        //  HashMap	HashMultiset	是
        //  TreeMap	TreeMultiset	是（如果comparator支持的话）
        //  LinkedHashMap	LinkedHashMultiset	是
        //  ConcurrentHashMap	ConcurrentHashMultiset	否
        //  ImmutableMap	ImmutableMultiset	否
        Multiset multiset = HashMultiset.create();
        multiset.count("1");

        //#####Map<T,List<V>>结构的map##########
        //  实现	键行为类似	值行为类似
        //  ArrayListMultimap	HashMap	ArrayList
        //  HashMultimap	HashMap	HashSet
        //  LinkedListMultimap*	LinkedHashMap*	LinkedList*
        //          LinkedHashMultimap**	LinkedHashMap	LinkedHashMap
        //  TreeMultimap	TreeMap	TreeSet
        //  ImmutableListMultimap	ImmutableMap	ImmutableList
        //  ImmutableSetMultimap	ImmutableMap	ImmutableSet
        Multimap<String, Integer> map = HashMultimap.create();
        map.put("a", 1); //key相同时不会覆盖原value
        map.put("a", 2);
        map.put("a", 3);
        System.out.println("-------- multimap");
        System.out.println(map); //{a=[1, 2, 3]}
        System.out.println(map.get("a")); //[1, 2, 3] 返回的是集合
        System.out.println(map.size()); //3 返回所有”键-单个值映射”的个数,而非不同键的个数
        System.out.println(map.keySet().size());  //1  返回不同key的个数
        Map<String, Collection<Integer>> mapView = map.asMap();

        //#########kv可以转换的 map##################
        //   键–值实现	值–键实现	对应的BiMap实现
        //   HashMap	HashMap	HashBiMap
        //   ImmutableMap	ImmutableMap	ImmutableBiMap
        //   EnumMap	EnumMap	EnumBiMap
        //   EnumMap	HashMap	EnumHashBiMap
        System.out.println("-------- bimap");

        BiMap<String, String> biMap = HashBiMap.create();
        biMap.put("sina", "sina.com");
        biMap.put("qq", "qq.com");
        biMap.put("sina", "sina.cn"); //会覆盖原来的value
       /*
         在BiMap中,如果你想把键映射到已经存在的值，会抛出IllegalArgumentException异常
         如果对特定值,你想要强制替换它的键，请使用 BiMap.forcePut(key, value)
        */
        // biMap.put("tecent", "qq.com"); //抛出异常
        biMap.forcePut("tecent", "qq.com"); //强制替换key
        System.out.println(biMap);
        System.out.println(biMap.inverse().get("sina.com")); //通过value找key
        System.out.println(biMap.inverse().inverse() == biMap); //true

        //#########可以按行列存放数据的数据结构###########
        // HashBasedTable：本质上用HashMap<R, HashMap<C, V>>实现；
        // TreeBasedTable：本质上用TreeMap<R, TreeMap<C,V>>实现；
        // ImmutableTable：本质上用ImmutableMap<R, ImmutableMap<C, V>>实现；注：ImmutableTable对稀疏或密集的数据集都有优化。
        // ArrayTable：要求在构造时就指定行和列的大小，本质上由一个二维数组实现，以提升访问速度和密集Table的内存利用率。ArrayTable与其他Table的工作原理有点不同，请参见Javadoc了解详情。
        //记录学生在某门课上的成绩
        System.out.println("-------- TABLE");
        Table<String, String, Integer> table = HashBasedTable.create();
        table.put("jack", "java", 100);
        table.put("jack", "c", 90);
        table.put("mike", "java", 93);
        table.put("mike", "c", 100);
        Set<Table.Cell<String, String, Integer>> cells = table.cellSet();
        for (Table.Cell<String, String, Integer> cell : cells) {
            System.out.println(cell.getRowKey() + " " + cell.getColumnKey() + " " + cell.getValue());
        }
        System.out.println(table.row("jack"));
        System.out.println(table);
        System.out.println(table.rowKeySet());
        System.out.println(table.columnKeySet());
        System.out.println(table.values());


        //########class作为key，instance作为value的map###############
        ClassToInstanceMap<String> classToInstanceMapString = MutableClassToInstanceMap.create();
        //###############区间操作RangeSet################################
        RangeSet<Integer> rangeSet = TreeRangeSet.create();
        rangeSet.add(Range.closed(1, 10)); // {[1,10]}
        rangeSet.add(Range.closedOpen(11, 15));//不相连区间:{[1,10], [11,15)}
        rangeSet.add(Range.closedOpen(15, 20)); //相连区间; {[1,10], [11,20)}
        rangeSet.add(Range.openClosed(0, 0)); //空区间; {[1,10], [11,20)}
        rangeSet.remove(Range.open(5, 10)); //分割[1, 10]; {[1,5], [10,10], [11,20)}
        //#######################RangeMap############################
        RangeMap<Integer, String> rangeMap = TreeRangeMap.create();
        rangeMap.put(Range.closed(1, 10), "foo"); //{[1,10] => "foo"}
        rangeMap.put(Range.open(3, 6), "bar"); //{[1,3] => "foo", (3,6) => "bar", [6,10] => "foo"}
        rangeMap.put(Range.open(10, 20), "foo"); //{[1,3] => "foo", (3,6) => "bar", [6,10] => "foo", (10,20) => "foo"}
        rangeMap.remove(Range.closed(5, 11)); //{[1,3] => "foo", (3,5) => "bar", (11,20) => "foo"}
    }
}
